package com.iflytek.uoamp.agent.monitor.find;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.iflytek.uoamp.agent.core.sender.monitorsender.responseObj.Status;

public class CMDExextor {

	private static final String EXCEPTION_EXECUTETIMEOUT = "脚本执行超时，请检查脚本。";
	// CountDownLatch计数器等待超时时间
	private static final int EXECUTE_AWAITTIMEOUT = 30;
	/**
	 * 如果要求可以dump；必须在脚本的perfild字段中输出pid的值
	 *
	 * @author gaowei
	 */
	public static class ShellResult{
		public String output;
		public String errOutput;
		public int code;
	}

	/**
	 * 命令执行,并返回执行结果
	 * */
	public static ShellResult execut(final boolean isLast,final String cmd,String[] evn){
		ShellResult result = new ShellResult();
		// 初始化为UNKNOWN = 3
		result.code = Status.UNKNOWN.getValue();
		try {
			Process ps = Runtime.getRuntime().exec(cmd, evn);
			// 记录代码执行过程中产生的异常信息：eg.执行脚本超时
			StringBuilder exceptionBuilder = new StringBuilder();
			// 记录脚本插件执行后，脚本输出的错误信息
			StringBuilder errBuilder = new StringBuilder();
			// 等待任务执行完成的信号量，在多个线程中共享
			CountDownLatch endSignal = new CountDownLatch(2);
			List<String> resultStandardList = new LinkedList<String>();
			List<String> resultErrorList = new LinkedList<String>();
			CMDExecutorWorkerJob StdJob = new CMDExecutorWorkerJob(endSignal, ps, cmd, resultStandardList);
			CMDExecutorWorkerJob errorJob = new CMDExecutorWorkerJob(endSignal, ps, cmd, resultErrorList, 1);
			try {
				CMDExecuteWorker.getInstance().submit(StdJob);
				CMDExecuteWorker.getInstance().submit(errorJob);
				// 当前线程等待最长30s,直到stdThread/errThread两线程执行完成
				boolean succeed = endSignal.await(EXECUTE_AWAITTIMEOUT, TimeUnit.SECONDS);
				Logger.getRootLogger().info(cmd + " : cmd plugin execute status : " + succeed);
				if(!succeed) {
					exceptionBuilder.append(EXCEPTION_EXECUTETIMEOUT);
					result.output = "";
					// 如果进程执行超时,杀死进程
					ps.destroy();
				} else {
					// 获取进程执行结果
					result.code = ps.waitFor();
					// 处理cmd执行标准输出流信息
					StringBuilder outputResult = new StringBuilder();
					if (isLast) {
						int stdResultSize = resultStandardList.size();
						if (stdResultSize != 0) {
							outputResult.append(resultStandardList.get(stdResultSize - 1));
						}
					} else {
						for (String line : resultStandardList) {
							outputResult.append(line);
						}
					}
					result.output = outputResult.toString();
					// 处理cmd执行错误输出流信息
					for (String line : resultErrorList) {
						errBuilder.append(line);
					}
				}
			} catch (InterruptedException e){
				Logger.getRootLogger().error(cmd + ": cmd plugin execute timeout.",e);
			} catch (Exception e) {
				String ioexceptionMsg = e.getMessage();
				exceptionBuilder.append(ioexceptionMsg);
				Logger.getRootLogger().error(ioexceptionMsg,e);
			} finally{
				// 处理异常信息
				String exceptionOutput = exceptionBuilder.toString();  
				if (!StringUtils.isBlank(exceptionOutput)) {
					errBuilder.append(exceptionOutput.replace(".", " "));
				}
				String errOutput = errBuilder.toString();
				result.errOutput = errOutput;
				if (!StringUtils.isBlank(errOutput)) {
					if(StringUtils.isNotBlank(result.output)){
						Logger.getLogger("pluginErrLogger").info("command " + cmd + " execute output infor : stdOutput-->" + result.output.concat(" & errOutput-->" + errOutput));
					}
					else{
						Logger.getLogger("pluginErrLogger").info("command " + cmd + " execute output infor : stdOutput-->" +result.output+  "|errOutput-->" + errOutput);
					}
				}
				// 清理结果列表
				resultStandardList.clear();
				resultErrorList.clear();
				exceptionBuilder.delete(0, exceptionBuilder.length());
				errBuilder.delete(0, errBuilder.length());
				// 杀死ps代表的进程
				ps.destroy();
			}
		} catch (IOException ioException) {
			Logger.getLogger("pluginErrLogger").info("command " + cmd + " execute exception-->" + ioException.getMessage());
		}
		return result;
	}

	/***
	 * 命令执行,并返回执行结果
 	 * @param cmd
	 * @param isLast	是否只取最后一行记录
	 * @return
	 */
	public static ShellResult execut(String cmd,boolean isLast){
		String[] cmds = cmd.split(" ");
		if (cmds[0].endsWith("jar")) {
			return execut(isLast, "java -Dfile.encoding=utf-8 -jar ".concat(cmd), null);
		} else {
			return execut(isLast, cmd, null);
		}
	}
	
	/**
	 * 默认全部取
	 * @param cmd
	 * @return
	 */
	public static ShellResult execut(String cmd){
		return execut(cmd,false);
	}
}
